package core;

import java.io.IOException;
import java.util.*;
import java.io.File;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException; 


public class TitratorXMLParser extends DefaultHandler
{
    private LinkedList<Component> components;
    private LinkedList<Specie> species;
    private String tempVal;
    private String fileName;
    private File file;
    private Component currentComp;
    private Specie currentSpecie;
    private boolean processingComp;
    private boolean processingSpecie;
    
    public TitratorXMLParser(File file)
    {
        //Instantiate the lists of chemical entities
        components = new LinkedList<Component>();
        species = new LinkedList<Specie>();
        
        //Set the file name
        this.file = file;
    }
    
    public void parseFile() throws SAXParseException, SAXException,
                                   IOException, Throwable
    {
        //Get a parser factory
        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();
        parser.parse(file, this);
    }
    
    //Handles the opening tag
    public void startElement(String uri, String localName, String qName, Attributes attributes) 
        throws SAXException 
    {
        tempVal = "";
        if(qName.equalsIgnoreCase("component"))
            {
                //Create a new component
                currentComp = new Component();
                processingSpecie = false;
                processingComp = true;
            }
        if(qName.equalsIgnoreCase("species"))
            {
                //Create a new component
                currentSpecie = new Specie();
                processingComp = false;
                processingSpecie = true;
            }
    }
    
    public void characters(char[] ch, int start, int length) throws SAXException 
    {
        tempVal = new String(ch,start,length);
    }
    
    public void endElement(String uri, String localName,
                           String qName) throws SAXException 
    {
        if (processingComp) 
            {
                if(qName.equalsIgnoreCase("component")) 
                    {
                        //add it to the list
                        components.add(currentComp);
                
                        System.out.println(currentComp);
                    }
                else if (qName.equalsIgnoreCase("Name")) 
                    {
                        currentComp.setName(tempVal);
                    }
                else if (qName.equalsIgnoreCase("type")) 
                    {
                        //Really ugly parsing of component type
//                         if(tempVal.equalsIgnoreCase("totdiss"))
//                             {
//                                 currentComp.setType(Component.CompType.TotDiss);
//                             }
//                         else if(tempVal.equalsIgnoreCase("fixdiss"))
//                             {
//                                 currentComp.setType(Component.CompType.FixDiss);
//                             }
//                         else if(tempVal.equalsIgnoreCase("redox"))
//                             {
//                                 currentComp.setType(Component.CompType.Redox);
//                             }
//                         else if(tempVal.equalsIgnoreCase("gas"))
//                             {
//                                 currentComp.setType(Component.CompType.Gas);
//                             }
//                         else if(tempVal.equalsIgnoreCase("solid"))
//                             {
//                                 currentComp.setType(Component.CompType.Solid);
//                             }
//                         else if(tempVal.equalsIgnoreCase("surface"))
//                             {
//                                 currentComp.setType(Component.CompType.Surface);
//                             }
                    }
                else if (qName.equalsIgnoreCase("charge")) 
                    {
                        currentComp.setCharge(Integer.parseInt(tempVal));
                    }
                else if(qName.equalsIgnoreCase("total_molarity"))
                    {
                        currentComp.setConc(Double.parseDouble(tempVal));
                    }
                else if(qName.equalsIgnoreCase("log_free_guess"))
                    {
                        currentComp.setGuess(Double.parseDouble(tempVal));
                    }
                else if(qName.equalsIgnoreCase("std_dev"))
                    {
                        currentComp.setStdDev(Double.parseDouble(tempVal));
                    }
            }
        if(processingSpecie)
            {
                if(qName.equalsIgnoreCase("specie")) 
                    {
                        //add it to the list
                        species.add(currentSpecie);
                        System.out.println(currentSpecie);
                    }
                else if (qName.equalsIgnoreCase("Name")) 
                    {
                        currentSpecie.setName(tempVal);
                    }
                else if (qName.equalsIgnoreCase("type")) 
                    {
                        //More ugly parsing for specie type
//                         if(tempVal.equalsIgnoreCase("diss"))
//                             {
//                                 currentSpecie.setType(Specie.SpecieType.Diss);
//                             }
//                         else if(tempVal.equalsIgnoreCase("solid"))
//                             {
//                                 currentSpecie.setType(Specie.SpecieType.Solid);
//                             }
//                         else if(tempVal.equalsIgnoreCase("gas"))
//                             {
//                                 currentSpecie.setType(Specie.SpecieType.Gas);
//                             }
//                         else if(tempVal.equalsIgnoreCase("surface"))
//                             {
//                                 currentSpecie.setType(Specie.SpecieType.Surface);
//                             }
//                         else if(tempVal.equalsIgnoreCase("sorbed"))
//                             {
//                                 currentSpecie.setType(Specie.SpecieType.Sorbed);
//                             }
                    }
                else if (qName.equalsIgnoreCase("deltaH")) 
                    {
                        currentSpecie.setDeltaH(Double.parseDouble(tempVal));
                    }
                else if (qName.equalsIgnoreCase("deltaS")) 
                    {
                        currentSpecie.setDeltaS(Double.parseDouble(tempVal));
                    }
                else if (qName.equalsIgnoreCase("deltaG")) 
                    {
                        currentSpecie.setDeltaG(Double.parseDouble(tempVal));
                    }
                else if (qName.equalsIgnoreCase("logK")) 
                    {
                        currentSpecie.setLogK(Double.parseDouble(tempVal));
                    }
                else if (qName.equalsIgnoreCase("std_dev")) 
                    {
                        currentSpecie.setStdDev(Double.parseDouble(tempVal));
                    }
            }
    }
}